<template>
  <div :class="`score-item ${dec ? 'win' : ''}`">
    <div class="total">
      <div class="txt">总分</div>
      <div
        class="num"
        :style="{ color: totalTextStyle(score_show.total) }"
      >
        {{ score_show.total }}
      </div>
    </div>
    <div class="math-t">=</div>
    <div class="type">
      <div class="txt">{{ score_show.type_s }}</div>
      <div class="num">{{ score_show.type }}</div>
    </div>
    <div class="math-t">+</div>
    <div class="code">
      <div class="txt">点数</div>
      <div class="num">{{ score_show.code }}</div>
    </div>
    <div class="math-t">+</div>
    <div class="spec">
      <div class="txt">特殊</div>
      <div class="num">{{ score_show.spec }}</div>
    </div>
  </div>
</template>

<script setup>
import { computed, reactive, ref, watch } from 'vue';

const IS_LOG = false; // （开发者模式）控制台打印
const props = defineProps({
  cards: { // 预设牌 + 区域牌
    type: Array,
    required: true,
  },
  effect: { // 场地效果对象
    type: Object,
    required: true,
  },
  field: { // 区域号
    type: String,
    required: true,
  },
  mode: { // 身份（his: 只显示上一回合分数, my）
    type: String,
    required: true,
  },
  pre: { // 历史回合分数对象
    type: Array,
    required: true,
  },
  round: { // 当前回合
    type: Number,
    required: true,
  },
  dec: { // 分数更高特效开启
    type: Boolean,
    default: false,
  },
});

const score = reactive({
  type_s: '无牌型', // 牌型名称
  total: 0, // 总分
  type: 0, // 牌型分
  code: 0, // 点数分
  spec: 0, // 特殊场地分
});
const score_show = computed(() => {
  if(props.round === 1 && props.mode === 'his') {
    return { type_s: '无牌型', total: 0, type: 0, code: 0, spec: 0 };
  } else if(props.mode === 'his') { // 对手仅显示上一回合的分数
    return props.pre[props.round - 2] || { type_s: '无牌型', total: 0, type: 0, code: 0, spec: 0 };
  }
  return score;
}); // 对外显示的分数
defineExpose({ score }); // 对外暴露分数对象

// 根据总分选择样式
const totalTextStyle = (total) => {
  if(total < 35) return 'white';
  if(total < 50) return '#c7c7ff';
  if(total < 80) return '#3ae64b';
  if(total < 100) return '#fdcbcb';
  if(total < 150) return '#f8b069';
  return '#f500ff';
};

const calculateScore = () => {
  // 计算点数分
  score.code = props.cards.reduce((pre, cur) => pre + cur.s, 0);
  // 计算牌型分
  const { tp, sc } = detectType(props.cards);
  score.type = sc;
  score.type_s = tp;
  // 计算场地分
  score.spec = 0;
  detectEffect(props.cards, props.effect);
  // 计算总分
  score.total = score.code + score.spec + score.type;
};

const FieldEffect = [ // 场地效果列表（前后端完全相同）
  {
    id: '1_none', // 场地效果ID
    name: '本区域无效果', // 场地效果名称
    extra: 'none', // meta数据
  },
  {
    id: '2_some1',
    name: '每有一张2，3，8，J加10分',
    extra: [ '2', '3', '8', 'J' ],
  },
  {
    id: '3_single1',
    name: '每有1张K加15分',
    extra: 'K',
  },
  {
    id: '4_color1',
    name: '每有1张红色牌加10分',
    extra: 'R',
  },
  {
    id: '5_color2',
    name: '若没有橙色牌加30分',
    extra: 'O',
  },
  {
    id: '6_color2',
    name: '每有1张蓝色牌加10分',
    extra: 'B',
  },
  {
    id: '7_type1',
    name: '本区域偶星额外加30分',
    extra: 'double',
  },
  {
    id: '8_principle1',
    name: '序列可以由4张牌组成',
    extra: 4,
  },
  {
    id: '9_principle2',
    name: '本区域无牌型加50分',
    extra: 'none',
  },
  {
    id: '10_code1',
    name: '点数和为奇数加25分',
    extra: 'single',
  },
];
const detectEffect = (cards, effect) => {
  if(effect.id === '1_none') {
    score.spec = 0;
    return ;
  }
  if(effect.id === '2_some1') {
    const list = cards.reduce((pre, cur) => {
      if(!pre[cur.t]) pre[cur.t] = 1;
      else pre[cur.t]++;
      return pre;
    }, {});
    for(let t of Object.keys(list)) {
      if(FieldEffect[1].extra.includes(t)) {
        score.spec += list[t] * 10;
      }
    }
    return ;
  }
  if(effect.id === '3_single1') {
    const list = cards.reduce((pre, cur) => {
      if(!pre[cur.t]) pre[cur.t] = 1;
      else pre[cur.t]++;
      return pre;
    }, {});
    if(list['K']) {
      score.spec = list['K'] * 15;
    } else {
      score.spec = 0;
    }
    return ;
  }
  if(effect.id === '4_color1') {
    const list = cards.reduce((pre, cur) => {
      if(!pre[cur.c]) pre[cur.c] = 1;
      else pre[cur.c]++;
      return pre;
    }, {});
    if(list['R']) {
      score.spec = list['R'] * 10;
    } else {
      score.spec = 0;
    }
    return ;
  }
  if(effect.id === '5_color2') {
    const list = cards.map(c => c.c);
    if(!list.includes('O')) score.spec = 30;
    else score.spec = 0;
    return ;
  }
  if(effect.id === '6_color2') {
    const list = cards.reduce((pre, cur) => {
      if(!pre[cur.c]) pre[cur.c] = 1;
      else pre[cur.c]++;
      return pre;
    }, {});
    if(list['B']) {
      score.spec = list['B'] * 10;
    } else {
      score.spec = 0;
    }
    return ;
  }
  if(effect.id === '7_type1' && score.type_s === '偶星') {
    score.spec = 30;
    return ;
  }
  if(effect.id === '8_principle1') {
    score.spec = 0;
    return ;
  }
  if(effect.id === '9_principle2' && score.type_s === '无牌型') {
    score.spec = 50;
    return ;
  }
  if(effect.id === '10_code1') {
    if(score.code % 2 === 1) {
      score.spec = 25;
    } else {
      score.spec = 0;
    }
    return ;
  }
};

// 牌型对照表
const CARDTYPE = {
  _none: { name: '无牌型', s: 0, }, // 牌型名 牌型分
  _double: { name: '偶星', s: 15, },
  _ddouble: { name: '双偶星', s: 30, },
  _triple: { name: '三贤者', s: 30, },
  _fullseat: { name: '满座', s: 55, },
  _samecolor: { name: '同色', s: 60, },
  _order: { name: '序列', s: 60, },
  _quad: { name: '四骑士', s: 80, },
  _ordersame: { name: '同色序列', s: 120, },
};
// 由分数最低的型往高分匹配牌型，高分覆盖低分作为最后牌型
const detectType = (cards) => {
  const result = {
    tp: CARDTYPE._none.name, // 牌型名
    sc: CARDTYPE._none.s, // 牌型分
  };
  const allCodes = cards.map(c => {
    if(c.t === 'J') return 11;
    if(c.t === 'Q') return 12;
    if(c.t === 'K') return 13;
    if(c.t === 'A') return 14;
    return Number(c.t);
  });
  const allCodes_ori = allCodes.slice(0);
  allCodes.sort((a, b) => a - b);
  if(IS_LOG) console.log(`场地${props.field}所有牌点`, allCodes);
  const allColors = allCodes_ori.map((c, i) => ({ t: c, c: cards[i].c }));
  const allColors_obj = {};
  if(IS_LOG) console.log(`场地${props.field}所有牌色`, allColors);
  // 检查顺序：偶星-双偶星-三贤者-满座-同色-序列-四骑士-同色序列-无牌型
  const checkList1 = allCodes.reduce((pre, cur) => { // 点
    if(!pre[cur]) pre[cur] = 1;
    else pre[cur]++;
    return pre;
  }, {});
  const checkList2 = allColors.reduce((pre, cur) => { // 色
    if(!pre[cur.c]) {
      pre[cur.c] = 1;
      allColors_obj[cur.c] = [];
    } else {
      pre[cur.c]++;
    }
    allColors_obj[cur.c].push(cur);
    return pre;
  }, {});
  let double_cnt = 0, triple_cnt = 0, quadruple_cnt = 0;
  for(let key of Object.keys(checkList1)) {
    if(checkList1[key] === 2) {
      result.tp = CARDTYPE._double.name; // 偶星
      result.sc = CARDTYPE._double.s;
      double_cnt++;
    }
    if(checkList1[key] === 3) {
      triple_cnt++;
    }
    if(checkList1[key] === 4) {
      quadruple_cnt++;
    }
  }
  if(double_cnt === 2) { // 双偶星
    result.tp = CARDTYPE._ddouble.name;
    result.sc = CARDTYPE._ddouble.s;
  }
  if(triple_cnt > 0) { // 三贤者
    result.tp = CARDTYPE._triple.name;
    result.sc = CARDTYPE._triple.s;
  }
  if(triple_cnt > 0 && double_cnt > 0) { // 满座
    result.tp = CARDTYPE._fullseat.name;
    result.sc = CARDTYPE._fullseat.s;
  }
  const sameCList = [];
  for(let key of Object.keys(checkList2)) {
    if(checkList2[key] >= 5) { // 同色
      result.tp = CARDTYPE._samecolor.name;
      result.sc = CARDTYPE._samecolor.s;
      sameCList.push(key);
      break;
    }
  }
  let isOrder = false;
  const len = cards.length;
  const allCodes_set = allCodes.reduce((pre, cur) => {
    if(!pre.includes(cur)) return [ ...pre, cur ];
    return pre;
  }, []);
  if(len > 4) { // 至少5张才能组成序列
    for(let i = 0; i < len; i++) {
      let j = i + 1;
      for(; j < len; j++) {
        if(allCodes_set[j] - allCodes_set[j - 1] !== 1) break;
      }
      if(j - i >= 5) {
        isOrder = true;
        break;
      }
    }
  }
  if(props.effect.id === '8_principle1' && len > 3) { // 序列可以由4张牌组成
    for(let i = 0; i < len; i++) {
      let j = i + 1;
      for(; j < len; j++) {
        if(allCodes_set[j] - allCodes_set[j - 1] !== 1) break;
      }
      if(j - i >= 4) {
        isOrder = true;
        break;
      }
    }
  }
  if(isOrder) { // 序列
    result.tp = CARDTYPE._order.name;
    result.sc = CARDTYPE._order.s;
  }
  if(quadruple_cnt > 0) { // 四骑士
    result.tp = CARDTYPE._quad.name;
    result.sc = CARDTYPE._quad.s;
  }
  let isSameOrder = false;
  sameCList.forEach(item => {
    const len = allColors_obj[item].length;
    allColors_obj[item].sort((a, b) => a.t - b.t);
    if(len > 4) {
      for(let i = 0; i < len; i++) {
        let j = i + 1;
        for(; j < len; j++) {
          if(allColors_obj[item][j].t - allColors_obj[item][j - 1].t !== 1) break;
        }
        if(j - i >= 5) {        
          isSameOrder = true;
          break;
        }
      }
    }
  });
  if(isSameOrder) { // 同色序列
    result.tp = CARDTYPE._ordersame.name;
    result.sc = CARDTYPE._ordersame.s;
  }
  return result;
};

watch([ () => props.cards, () => props.effect ], () => {
  if(IS_LOG) console.log(`${props.mode === 'my' ? '我的' : '对方'}区域${props.field}变更`, props.cards, props.effect);
  calculateScore(); // 计算分数
});

</script>

<style lang="scss" scoped>
::-webkit-scrollbar {
  display: none;
}
.score-item {
  width: 190px;
  line-height: 34px;
  color: white;
  font-size: 12px;
  display: flex;
}
.win {
  background-color: rgba(255, 152, 152, 0.6);
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 
      0 0 2px rgba(255, 60, 242, 0.9),
      0 0 4px rgba(255, 60, 242, 0.6),
      0 0 6px rgba(255, 60, 242, 0.4),
      0 0 8px rgba(255, 60, 242, 0.2);
}
.math-t {
  width: 5px;
  height: 34px;
}
.total {
  width: 38px;
  height: 34px;
  background-color: rgba(189, 189, 189, 0.658);
  border-radius: 10px;
  margin-right: 3px;
  .txt {
    overflow: auto;
    white-space: nowrap;
    width: 100%;
    line-height: 14px;
    font-weight: bold;
    text-align: center;
    color: rgb(0, 255, 162);
  }
  .num {
    width: 100%;
    line-height: 20px;
    text-align: center;
    font-weight: bold;
    font-size: 14px;
  }
}
.type {
  width: 43px;
  height: 34px;
  .txt {
    overflow: auto;
    white-space: nowrap;
    width: 100%;
    line-height: 14px;
    text-align: center;
  }
  .num {
    width: 100%;
    line-height: 20px;
    text-align: center;
  }
}
.code {
  width: 43px;
  height: 34px;
  .txt {
    overflow: auto;
    white-space: nowrap;
    width: 100%;
    line-height: 14px;
    text-align: center;
  }
  .num {
    width: 100%;
    line-height: 20px;
    text-align: center;
  }
}
.spec {
  width: 43px;
  height: 34px;
  .txt {
    overflow: auto;
    white-space: nowrap;
    width: 100%;
    line-height: 14px;
    text-align: center;
  }
  .num {
    width: 100%;
    line-height: 20px;
    text-align: center;
  }
}
</style>
